﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Web;

namespace Streaming_Service.Media {
    using System.Diagnostics;
    using System.IO;

    using Streaming_Service.FileTransfer;

    public class MediaFunc {
        public static string TmpFolder = @"Web\Media\Tmp\";
        public static string thumbFolder = @"Web\Media\Thumbs\";

        public static HashSet<string> thumbFileExtensions = new HashSet<string>
            { ".jpg", ".jpeg", ".gif", ".bmp", ".png", ".tif", ".tiff" };

        public static string movieFolderSD = @"Web\Media\Movies\SD\";
        public static string movieFolderHD = @"Web\Media\Movies\HD\";

        public static HashSet<string> movieFileExtensions = new HashSet<string> { ".avi", ".mp4", ".mkv", ".mov", ".flv" };

        public static Dictionary<string, string> mimeTypes = new Dictionary<string, string>
            {
                { ".jpg", "image/jpeg" },
                { ".jpeg", "image/jpeg" },
                { ".giff", "image/gif" },
                { ".bmp", "image/x-bitmap" },
                { ".png", "image/png" },
                { ".tif", "image/tif" },
                { ".tiff", "image/tiff" },
                {".avi", "video/x-msvideo"},
                {".mp4", "video/mp4"},
                {".mkv", "video/x-matroska"},
                {".flv", "video/x-flv"}
            };

        public static string defaultMimeType = "application/octet-stream";

        public static string RootFolder() {
            return (HttpContext.Current != null
                        ? HttpContext.Current.Request.PhysicalApplicationPath
                        : AppDomain.CurrentDomain.BaseDirectory);
        }

        public static string RootUrl() {
            return Environment.MachineName == "RENTIT" ? RentIt11.BaseUrl.Replace("://rentit/", "://rentit.itu.dk/") : RentIt11.BaseUrl;
        }

        public static bool ThumbFolderExists(int movieId) {
            return ThumbFolderExists(movieId, RootFolder());
        }

        public static bool ThumbFolderExists(int movieId, string rootPath) {
            return Directory.Exists(rootPath + thumbFolder + movieId);
        }

        public static string GetThumbFolder(int movieId) {
            return GetThumbFolder(movieId, RootFolder());
        }

        public static string GetThumbFolder(int movieId, string rootPath) {
            return rootPath + thumbFolder + movieId + "\\";
        }

        public static string GetThumbPath(int movieId) {
            return GetThumbPath(movieId, RootFolder());
        }

        public static string GetThumbPath(int movieId, string rootPath) {
            if (Directory.Exists(rootPath + thumbFolder + movieId)) {
                var dirInfo = new DirectoryInfo(rootPath + thumbFolder + movieId);
                foreach (var file in dirInfo.GetFiles()) {
                    if (thumbFileExtensions.Contains(file.Extension)) return file.FullName;
                }
            }
            return string.Empty;
        }

        public static bool MovieFolderExists(int movieId, bool HD) {
            return MovieFolderExists(movieId, RootFolder(), HD);
        }

        public static bool MovieFolderExists(int movieId, string rootPath, bool HD) {
            return Directory.Exists(rootPath + (HD ? movieFolderHD : movieFolderSD) + movieId);
        }

        public static string GetMovieFolder(int movieId, bool HD) {
            return GetMovieFolder(movieId, RootFolder(), HD);
        }

        public static string GetMovieFolder(int movieId, string rootPath, bool HD) {
            var movieFolder = (HD ? movieFolderHD : movieFolderSD);
            return rootPath + movieFolder + movieId + "\\";
        }

        public static string GetMoviePath(int movieId, bool HD) {
            return GetMoviePath(movieId, RootFolder(), HD);
        }

        public static string GetMoviePath(int movieId, string rootPath, bool HD) {
            if (Directory.Exists(GetMovieFolder(movieId, HD))) {
                var dirInfo = new DirectoryInfo(GetMovieFolder(movieId, HD));
                foreach (var file in dirInfo.GetFiles()) {
                    if (movieFileExtensions.Contains(file.Extension)) return file.FullName;
                }
            }
            return string.Empty;
        }

        public static string GetContentType(string filename) {
            if(File.Exists(filename)) {
                var file = new FileInfo(filename);
                if(mimeTypes.ContainsKey(file.Extension)) {
                    return mimeTypes[file.Extension];
                }
            }
            return defaultMimeType;
        }

        public static void CreateMovieFolder(int movieId) {
            var folders = new []
                {
                    RootFolder() + movieFolderSD, GetMovieFolder(movieId, false), RootFolder() + movieFolderHD,
                    GetMovieFolder(movieId, true), RootFolder() + thumbFolder, GetThumbFolder(movieId)
                };

            foreach (var folder in folders.Where(folder => !Directory.Exists(folder))) {
                Directory.CreateDirectory(folder);
            }
        }

        #region "Empty Folder/Directory"
        public static void EmptyFoldersForMovie(int movieId) {
            EmptyMovieFolders(movieId);
            EmptyThumbFolder(movieId);
        }

        public static void EmptyMovieFolders(int movieId) {
            EmptyMovieFolderSD(movieId);
            EmptyMovieFolderHD(movieId);
        }

        public static void EmptyMovieFolderSD(int movieId) {
            EmptyDirectory(GetMovieFolder(movieId, false));
        }

        public static void EmptyMovieFolderHD(int movieId) {
            EmptyDirectory(GetMovieFolder(movieId, true));
        }

        public static void EmptyThumbFolder(int movieId) {
            EmptyDirectory(GetThumbFolder(movieId));
        }

        public static void EmptyDirectory(string path) {
            if (Directory.Exists(path)) {
                var dirInfo = new DirectoryInfo(path);
                EmptyDirectory(dirInfo);
            }
        }

        public static void EmptyDirectory(DirectoryInfo dirInfo) {
            if (dirInfo.Exists) {
                foreach (var file in dirInfo.GetFiles()) {
                    if (File.Exists(file.FullName)) {
                        File.SetAttributes(file.FullName, FileAttributes.Normal);
                        File.Delete(file.FullName);
                    }
                }
            }
        }
        #endregion

        #region "Delete Folder/Directory"
        public static void DeleteFoldersForMovie(int movieId) {
            DeleteMovieFolders(movieId);
            DeleteThumbFolder(movieId);
        }

        public static void DeleteMovieFolders(int movieId) {
            DeleteMovieFolderSD(movieId);
            DeleteMovieFolderHD(movieId);
        }

        public static void DeleteMovieFolderSD(int movieId) {
            ProperDeleteFolder(GetMovieFolder(movieId, false));
        }

        public static void DeleteMovieFolderHD(int movieId) {
            ProperDeleteFolder(GetMovieFolder(movieId, true));
        }

        public static void DeleteThumbFolder(int movieId) {
            ProperDeleteFolder(GetThumbFolder(movieId));
        }

        public static void ProperDeleteFolder(string path, int retry = 0) {
            if(Directory.Exists(path)) {
                var dirInfo = new DirectoryInfo(path);

                EmptyDirectory(dirInfo);

                foreach(var dir in dirInfo.GetDirectories()) {
                    ProperDeleteFolder(dir.FullName);
                }

                try {
                    Directory.Delete(dirInfo.FullName, true);
                } catch(UnauthorizedAccessException uae) {
                    Console.Write(uae);
                    if(retry < 3) ProperDeleteFolder(dirInfo.FullName, ++retry);
                }
            }
        }
        #endregion

        public static void EnsureTmpFolderExists() {
            if (!Directory.Exists(GetTmpFolder())) Directory.CreateDirectory(GetTmpFolder());
        }

        public static string GetTmpFolder() {
            return RootFolder() + TmpFolder;
        }

        public static bool MoveMovieFile(int movieId, UploadFileInfo fileInfo) {
            if (fileInfo == null || string.IsNullOrEmpty(fileInfo.Filename) || string.IsNullOrEmpty(fileInfo.TmpFilename)) return false;
            
            if(fileInfo.IsHD) {
                EmptyMovieFolderHD(movieId);
            }else {
                EmptyMovieFolderSD(movieId);
            }

            var newFilename = GetMovieFolder(movieId, fileInfo.IsHD) + fileInfo.Filename;
            File.Move(fileInfo.TmpFilename, newFilename);
            return File.Exists(newFilename);
        }

        public static bool MoveThumbFile(int movieId, UploadFileInfo fileInfo) {
            if (fileInfo == null || string.IsNullOrEmpty(fileInfo.Filename) || string.IsNullOrEmpty(fileInfo.TmpFilename)) return false;
            EmptyThumbFolder(movieId);
            var newFilename = GetThumbFolder(movieId) + fileInfo.Filename;
            File.Move(fileInfo.TmpFilename, newFilename);
            return File.Exists(newFilename);
        }

        public static bool ValidYear(int year) {
            return year >= 1750 && year <= 3000;
        }

        public static bool ValidLength(int length) {
            return length > 0 && length < 7 * 24 * 60;
        }

        public static bool ValidReleaseDate(DateTime? releaseDate) {
            return releaseDate != null && releaseDate.Value.Year >= 1750 && releaseDate.Value.Year <= 3000;
        }
    }
}